package com.mmall.demo2;

import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;

@Configuration
public class ShiroConfiguration {

    // Shiro核心配置类

    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(manager);

        bean.setLoginUrl("/login");  // 登录的url
        bean.setSuccessUrl("/index");  // 默认的url
        bean.setUnauthorizedUrl("/unauthorized");  // 没有认证的url

        // 下边配置请求应该怎么拦截
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 第一个参数是拦截的哪个url，第二个参数是让哪个拦截器拦截
        filterChainDefinitionMap.put("/index", "authc");  // authc是必须校验
        filterChainDefinitionMap.put("/login", "anon");  // anon不需要校验
        filterChainDefinitionMap.put("/loginUser", "anon");
        filterChainDefinitionMap.put("/admin", "roles[admin]");  // 通过角色控制，不同的角色访问不同的页面，此处只有admin这个角色才可以访问admin这个接口  验证接口是RolesAuthorizationFilter
        filterChainDefinitionMap.put("/edit", "perms[edit]");  // 具有edit权限的permission才可以访问edit这个接口  验证接口是(PermissionsAuthorizationFilter)
        filterChainDefinitionMap.put("/druid/**", "anon");
        filterChainDefinitionMap.put("/**", "user");  // user是判断是否登录
        bean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return bean;
    }

    // 设置安全管理器
    @Bean("securityManager")
    public SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm) {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(authRealm);
        return manager;
    }

    @Bean("authRealm")
    public AuthRealm authRealm(@Qualifier("credentialMatcher") CredentialMatcher matcher) {
        AuthRealm authRealm = new AuthRealm();
        authRealm.setCacheManager(new MemoryConstrainedCacheManager());  // 可以使用cache缓存，这儿是在内存中缓存
        authRealm.setCredentialsMatcher(matcher);  // 给出自己的比较器
        return authRealm;
    }

    // 定义自己的校验规则
    @Bean("credentialMatcher")
    public CredentialMatcher credentialMatcher() {
        return new CredentialMatcher();
    }


    ////// 使用下面的两个类配置后，shiro完全是我们自定义的了
    // 设置spring处理的SecurityManager是我们自定义的
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }



    // 使用代理，
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);  // 默认是false
        return creator;
    }
}
